/**
 * Date:2017年10月17日下午6:14:36
 * Copyright (c) 2017, www.bwbroad.com All Rights Reserved.
 *
 */

package ssh;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import org.apache.commons.io.IOUtils;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

/**
 * Description: ssh远程登录并执行脚本和文件上传下载 <br/>
 * Date: 2017年10月17日 下午6:14:36 <br/>
 * 
 * @author xuejianxin
 */
public class RemoteShellExecutor {
	/** 连接 */
	private Connection conn;
	/** 远程机器IP */
	private String ip;
	/** 用户名 */
	private String username;
	/** 密码 */
	private String password;
	/** 字符集 */
	private String charset = Charset.defaultCharset().toString();
	/** 超时时间 */
	private static final int TIME_OUT = 1000 * 60 * 60;
	/** 命令计数 */
	private int count = 1;

	/**
	 * 构造函数
	 * 
	 * @param ip
	 * @param usr
	 * @param pasword
	 */
	public RemoteShellExecutor(String ip, String username, String pasword) {
		this.ip = ip;
		this.username = username;
		this.password = pasword;
	}

	/**
	 * 登录
	 * 
	 * @return
	 * @throws IOException
	 */
	private boolean login() throws IOException {
		if (null == conn) {
			conn = new Connection(ip);
			conn.connect();
			return conn.authenticateWithPassword(username, password);
		}
		return true;
	}

	/**
	 * 
	 * Description:上传文件<br/>
	 * Date: 2017年10月31日 下午2:54:27 <br/>
	 * 
	 * @author xuejianxin
	 * @param localFile
	 *            本地文件全路径
	 * @param remoteDir
	 *            远程目录
	 * @throws IOException
	 */
	public int uploadFile(String localFile, String remoteDir)
			throws IOException {
		login();
		SCPClient scpClient = conn.createSCPClient();
		System.out
				.printf("\n======================================>>执行第%d条命令\n-------------------------\n",
						count++);
		System.out.printf("upload File:%s --> %s", localFile, remoteDir);
		scpClient.put(localFile, remoteDir);
		System.out
				.println("................................................................");
		return 0;
	}

	/**
	 * 
	 * Description:下载文件<br/>
	 * Date: 2017年10月31日 下午2:54:54 <br/>
	 * 
	 * @author xuejianxin
	 * @param remoteFile
	 *            远程文件
	 * @param localDir
	 *            本地目录
	 * @throws IOException
	 */
	public int downloadFile(String remoteFile, String localDir)
			throws IOException {
		login();
		SCPClient scpClient = conn.createSCPClient();
		System.out
				.printf("\n======================================>>执行第%d条命令\n-------------------------\n",
						count++);
		System.out.printf("download File:%s --> %s", remoteFile, localDir);
		scpClient.get(remoteFile, localDir);
		System.out
				.println("................................................................");
		return 0;
	}

	/**
	 * 执行脚本
	 * 
	 * @param cmds
	 * @return
	 * @throws Exception
	 */
	public int exec(String cmds) throws Exception {
		InputStream stdOut = null;
		InputStream stdErr = null;
		String outStr = "";
		String outErr = "";
		int ret = -1;
		Session session = null;
		try {
			login();
			// 打开一个新session
			session = conn.openSession();
			// 执行命令
			session.execCommand(cmds);

			stdOut = new StreamGobbler(session.getStdout());
			outStr = processStream(stdOut, charset);

			stdErr = new StreamGobbler(session.getStderr());
			outErr = processStream(stdErr, charset);

			session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
			ret = session.getExitStatus();
			System.out
					.printf("\n======================================>>执行第%d条命令\n%s\n-------------------------\n",
							count++, cmds);
			System.out.printf("控制台结果:\n%s\n\n", outStr);
			System.out.printf("错误信息:\n%s\n\n", outErr);
			System.out
					.println("................................................................");
			if (0 != ret) {
				throw new Exception(String.format("执行命令%s失败", cmds)); // 自定义异常类
																		// 实现略
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (null != session) {
				session.close();
			}

			IOUtils.closeQuietly(stdOut);
			IOUtils.closeQuietly(stdErr);
		}
		return ret;
	}

	public boolean closeConn() {
		if (null != conn) {
			conn.close();
		}
		return true;
	}

	/**
	 * @param in
	 * @param charset
	 * @return
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	private String processStream(InputStream in, String charset)
			throws Exception {
		byte[] buf = new byte[1024];
		StringBuilder sb = new StringBuilder();
		while (in.read(buf) != -1) {
			sb.append(new String(buf, charset));
		}
		return sb.toString();
	}

	public static void main(String args[]) throws Exception {
		/**
		 * 执行单个命令 RemoteShellExecutor executor = new
		 * RemoteShellExecutor("172.16.10.111", "root", "bwie2014");
		 * executor.exec("ls -lh"); executor.exec("pwd");
		 * executor.exec("cd / && ls -lh"); executor.closeConn();
		 */
		/** 执行配置文件命令 */
		CmdTool.parserAndExecute("D:/java/workspace20160510bwie/nuomi/src/ssh/cmd1.txt");
	}

}
